﻿using System.Net;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Qzb.MicroService.Common.ConsulExtensions.Client;
using Qzb.MicroService.Common.ConsulExtensions.Register;

namespace Qzb.MicroService.Common.ConsulExtensions
{
    public static class ConsulExtensions
    {
        /// <summary>
        /// 注册IOC
        /// </summary>
        /// <param name="services"></param>
        public static void AddConsulRegister(this IServiceCollection services)
        {
            services.AddTransient<IConsulRegister, ConsulRegister>();
        }

        /// <summary>
        /// 注册Consul调度策略
        /// </summary>
        /// <param name="services"></param>
        /// <param name="dispatcherType"></param>
        public static void AddConsulDispatcher(this IServiceCollection services, ConsulDispatcherType dispatcherType)
        {
            switch (dispatcherType)
            {
                case ConsulDispatcherType.Random:
                    services.AddTransient<ConsulDispatcher, ConsulRandomDispatcher>();
                    break;
                case ConsulDispatcherType.Polling:
                    services.AddTransient<ConsulDispatcher, ConsulPollingDispatcher>();
                    break;
                case ConsulDispatcherType.Weight:
                    services.AddTransient<ConsulDispatcher, ConsulWeightDispatcher>();
                    break;
            }
        }

        /// <summary>
        /// 注册Consul
        /// </summary>
        /// <param name="app"></param>
        public static void UseConsulRegister(this IApplicationBuilder app, IHostApplicationLifetime lifetime)
        {
            var service = app.ApplicationServices.GetService<IConsulRegister>();
            if (service == null) return;

            var healthCheckPath = GetHealthCheckPath(app);
            MapHealthCheckApi(app, healthCheckPath);

            service.ServiceRegister().Wait();

            lifetime.ApplicationStopping.Register(() =>
            {
                service.ServiceDeregister().Wait();
            });
        }

        /// <summary>
        /// 设置心跳响应接口
        /// </summary>
        private static void MapHealthCheckApi(IApplicationBuilder app, string path)
        {
            app.Map(path, applicationBuilder => applicationBuilder.Run(async context =>
            {
                Console.WriteLine($"This is Health Check");
                context.Response.StatusCode = (int)HttpStatusCode.OK;
                await context.Response.WriteAsync("OK");
            }));
        }

        private static string GetHealthCheckPath(IApplicationBuilder app, string? path = null)
        {
            if (!string.IsNullOrEmpty(path))
                return path;

            var options = app.ApplicationServices.GetService<IOptionsMonitor<ConsulRegisterOptions>>();
            path = options?.CurrentValue?.HealthCheckApiPath;
            if (string.IsNullOrEmpty(path)) path = "/api/health";
            if (!path.StartsWith('/')) path = $"/{path}";

            if (options?.CurrentValue != null) options.CurrentValue.HealthCheckApiPath = path;

            return path;
        }
    }
}
